﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;

namespace GpxTool
{

    public class PointF
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Z { get; set; }

        public void Set(double _x, double _y)
        {
            X = _x;
            Y = _y;
        }
    }

    public class GpsTool
    {
        
        static public PointF GPSToPixelXY(double lat, double lon)
        {
            lon = lon / 360.0 + 0.5;

            lat = 0.5 - (Math.Log(Math.Tan((Math.PI / 4.0) + (Math.PI / 2.0) * lat / 180.0)) / Math.PI) / 2.0;
            lat = Math.Max(0.0, lat);
            lat = Math.Min(1.0, lat);

            PointF result = new PointF();

            result.Set((lon * 400396.28f),
                    400396.28125f - (lat * 400396.28f));

            return result;
        }

        static double Rmod(double a, double b)
        {
            long div = (long)(a / b);
            return a - (double)div * b;
        }

        static public PointF PixelXYToGPS(double x, double y)
        {

            double lat = (400396.28125f - y) / 400396.28f;
            double lon = x / 400396.28f;

            lat = Math.Max(0, lat);
            lat = Math.Min(1, lat);

            if (lat == 0)
                lat = 90.0f;
            else if (lat == 1.0f)
                lat = -90.0f;
            else
                lat = (180.0f / Math.PI) * (2.0f * Math.Atan(Math.Exp(Math.PI * (1.0f - 2.0f * lat))) - (Math.PI / 2.0f));

            if (lon >= 0)
            {
                lon = Rmod(lon, 1.0f);
            }
            else
            {
                lon = Rmod(1.0f - Rmod(-1.0f * lon, 1.0f), 1.0f);
            }

            lon = (lon - 0.5) * 360;

            PointF result = new PointF();
            result.Set((float)lat, (float)lon);

            return result;
        }

        static public double StrToDouble(string val)
        {
            double ret = 0.0;
            val = Regex.Replace(val, @"\,|\.", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
            ret = Convert.ToDouble(val);
            return ret;
        }
        static public string DoubleToStr(double val)
        {
            string ret = val.ToString();
            ret = Regex.Replace(ret, @"\,|\.", @".");
            return ret;
        }
    }

    public class GpxFormat
    {

        #region metadata
        public string creator;
        public string link;
        public string linkText;
        public string time;
        #endregion

        public ObservableCollection<Track> trk;

        public GpxFormat()
        {
            creator = "";
            link = "";
            linkText = "";
            time = "";
            trk = new ObservableCollection<Track>();
        }
    }

    public class Track
    {
        public string trackName { get; set; }
        public ObservableCollection<TrackSeg> trkseg;

        public Track()
        {
            trackName = "";
            trkseg = new ObservableCollection<TrackSeg>();
        }
    }

    public class TrackSeg
    {
        public ObservableCollection<TrackPoint> trkpt;

        public TrackSeg()
        {
            trkpt = new ObservableCollection<TrackPoint>();
        }
    }

    public class TrackPoint
    {
        public double lat;
        public double lon;
        public double ele;
        public string time;

        public TrackPoint()
        {
            lat = 0.0;
            lon = 0.0;
            ele = 0.0;
            time = "";
        }

        public TrackPoint(double _lat, double _lon, double _ele, string _time)
        {
            lat = _lat;
            lon = _lon;
            ele = _ele;
            time = _time;
        }

    }

}
